import 'dart:convert';
import 'dart:math';

import 'package:aero_frisbee/app/conf/local_resource.dart';
import 'package:aero_frisbee/app/model/af_home_user_model/af_home_user_model.dart';
import 'package:aero_frisbee/app/model/cache_bind_model/cache_bind_model.dart';
import 'package:aero_frisbee/app/model/local_post_model/local_post_model.dart';
import 'package:aero_frisbee/app/req/af_req_api.dart';
import 'package:aero_frisbee/app/state/app_cache_state.dart';
import 'package:flutter/foundation.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'af_home_view_model.g.dart';

@Riverpod(keepAlive: true)
List<LocalPostModel> createdPostByAuthor(CreatedPostByAuthorRef ref,
    {required String author}) {
  final homePost = ref.watch(afHomePostListServiceProvider);
  final homeList = homePost.maybeWhen(
    orElse: () => List<LocalPostModel>.from([]),
    data: (data) => data,
  );
  return homeList
      .where(
        (element) => element.author == author,
      )
      .toList();
}

@Riverpod(keepAlive: true)
LocalPostModel createdPostByUid(CreatedPostByUidRef ref, {required int uid}) {
  final homePost = ref.watch(afHomePostListServiceProvider);
  final homeList = homePost.maybeWhen(
    orElse: () => List<LocalPostModel>.from([]),
    data: (data) => data,
  );
  return homeList
      .where(
        (element) => element.uid == uid,
      )
      .toList()
      .last;
}

@Riverpod(keepAlive: true)
class AfHomeUserListService extends _$AfHomeUserListService {
  @override
  FutureOr<List<AfHomeUserModel>> build() {
    return ref.read(appApiProvider).fetchBroadcaster();
  }
}

@Riverpod(keepAlive: true)
class AfHomePostListService extends _$AfHomePostListService {
  @override
  FutureOr<List<LocalPostModel>> build() async {
    final bindList = ref.watch(homeBindCacheUserListServiceProvider);
    if (bindList.isNotEmpty) {
      final retlist = LocalResource.resList
          .map(
            (e) => e.copyWith(
                cacheBind: bindList.lastWhere(
              (element) => element.author == e.author,
            )),
          )
          .toList();
      return Future.value(retlist);
    } else {
      final userList = await ref.read(appApiProvider).fetchBroadcaster();
      List<CacheBindModel> cacheBindList = [];
      var authorList = LocalResource.resList
          .map(
            (e) => e.author ?? '',
          )
          .toSet()
          .toList();
      authorList.shuffle(Random());

      debugPrint('🐸authorList: $authorList, \n 总共作者为:${authorList.length}');

      for (var i = 0; i < authorList.length; i++) {
        var element = authorList[i];
        cacheBindList.add(CacheBindModel(
          author: element,
          homeUser: userList.isNotEmpty ? userList[i] : userList.last,
        ));
      }
      ref
          .read(homeBindCacheUserListServiceProvider.notifier)
          .update(cacheBindList);

      return Future.value(LocalResource.resList
          .map(
            (e) => e.copyWith(
                cacheBind: cacheBindList.lastWhere(
              (element) => element.author == e.author,
            )),
          )
          .toList());
    }
  }

  toggleLike(int uid) {
    final curPostList = state.maybeWhen(
      orElse: () => List<LocalPostModel>.from([]),
      data: (data) => data,
    );
    final retList = curPostList.map((e) {
      if (e.uid == uid) {
        return e.copyWith(isLike: !e.isLike);
      } else {
        return e;
      }
    }).toList();
    state = AsyncData(retList);
  }
}

@Riverpod(keepAlive: true)
class HomeBindCacheUserListService extends _$HomeBindCacheUserListService {
  @override
  List<CacheBindModel> build() {
    final userId = ref.watch(curlUserInfoProvider)?.userInfoModel?.userId;
    if (userId != null) {
      final prefs = ref.read(appPrefsProvider);
      final bindListStr = prefs.getString('bind.user.list.key_$userId');
      if (bindListStr != null && bindListStr.isNotEmpty) {
        final bindList = List<CacheBindModel>.from(
            jsonDecode(bindListStr).map((x) => CacheBindModel.fromJson(x)));
        return bindList;
      }
    }
    return [];
  }

  update(List<CacheBindModel> list) async {
    state = list;
    final userId = ref.read(curlUserInfoProvider)?.userInfoModel?.userId;
    if (userId != null) {
      final prefs = ref.read(appPrefsProvider);
      await prefs.setString('bind.user.list.key_$userId', jsonEncode(list));
    }
  }
}
